"""
Statement Transformation Rules.

This module provides concrete transformation rules for C# statements to C++ equivalents.
"""

from typing import Any

from orchestrator.ir.nodes import ForeachStatement, IfStatement, Statement
from orchestrator.transforms.rules import (
    RuleMetadata,
    StatementTransformationRule,
    TransformationPhase,
)


class IfStatementTransformer(StatementTransformationRule):
    """
    Transforms C# if statements to C++ if statements.

    This is mostly a pass-through transformation, but demonstrates the pattern
    and can be extended to handle C#-specific patterns.
    """

    def __init__(self) -> None:
        metadata = RuleMetadata(
            name="if_statement_transform",
            version="1.0.0",
            description="Transform C# if statements to C++ if statements",
            priority=100,
            phase=TransformationPhase.NORMALIZATION,
            tags=["statement", "control-flow"],
        )
        super().__init__(metadata, target_statement_kind="if")

    def can_apply(self, node: Any) -> bool:
        """Check if this is an if statement"""
        return isinstance(node, IfStatement)

    def apply(self, node: Any) -> Any:
        """
        Apply transformation to if statement.

        For now, this is a pass-through, but could be extended to:
        - Transform C# 'is' patterns to C++ equivalent
        - Handle null-coalescing operators
        - Transform string comparisons
        """
        if not isinstance(node, IfStatement):
            return node

        # In a real implementation, we might transform the condition
        # For example: "if (obj is string s)" -> "if (auto* s = dynamic_cast<string*>(obj))"
        # For now, we just pass through
        return node


class ForeachToRangeForTransformer(StatementTransformationRule):
    """
    Transforms C# foreach statements to C++ range-based for loops.

    C#: foreach (var item in collection)
    C++: for (auto& item : collection)
    """

    def __init__(self) -> None:
        metadata = RuleMetadata(
            name="foreach_to_range_for",
            version="1.0.0",
            description="Transform C# foreach to C++ range-based for loop",
            priority=100,
            phase=TransformationPhase.NORMALIZATION,
            tags=["statement", "loop", "foreach"],
        )
        super().__init__(metadata, target_statement_kind="foreach")

    def can_apply(self, node: Any) -> bool:
        """Check if this is a foreach statement"""
        return isinstance(node, ForeachStatement)

    def apply(self, node: Any) -> Any:
        """
        Transform foreach to range-based for.

        The transformation:
        - 'var' -> 'auto'
        - 'in collection' -> ': collection'
        - Decide between auto, auto&, const auto& based on usage
        """
        if not isinstance(node, ForeachStatement):
            return node

        # Create a transformed statement with C++ syntax metadata
        transformed = ForeachStatement(
            variable_type=self._transform_type(node.variable_type),
            variable_name=node.variable_name,
            collection=node.collection,
            body=node.body,
            metadata={
                **node.metadata,
                "cpp_loop_style": "range_based_for",
                "cpp_variable_qualifier": self._determine_qualifier(node),
                "original_csharp_type": node.variable_type,
            },
        )

        return transformed

    def _transform_type(self, csharp_type: str) -> str:
        """
        Transform C# type to C++ auto qualifier.

        Args:
            csharp_type: C# type (e.g., 'var', 'string', 'int')

        Returns:
            C++ auto qualifier (e.g., 'auto', 'auto&', 'const auto&')
        """
        # 'var' always becomes 'auto' with appropriate qualifier
        if csharp_type == "var":
            return "auto"

        # For specific types, we might want different qualifiers
        # For now, use auto for consistency
        return "auto"

    def _determine_qualifier(self, node: ForeachStatement) -> str:
        """
        Determine the appropriate C++ qualifier (ref, const ref, value).

        In a real implementation, we would analyze the loop body to determine:
        - If the variable is modified -> auto&
        - If the variable is only read and is expensive to copy -> const auto&
        - If the variable is primitive or small -> auto (value copy)

        For now, we default to const auto& (safe and efficient).
        """
        # Heuristic: If type is a value type (int, bool, etc.), use auto
        # Otherwise use const auto& (reference to avoid copying)
        value_types = {"int", "bool", "float", "double", "char", "byte", "short", "long"}

        if node.variable_type.lower() in value_types:
            return "auto"

        return "const auto&"


class NullCheckTransformer(StatementTransformationRule):
    """
    Transforms C# null checks to C++ nullptr checks.

    C#: if (obj == null)
    C++: if (obj == nullptr)

    C#: if (obj != null)
    C++: if (obj != nullptr)
    """

    def __init__(self) -> None:
        metadata = RuleMetadata(
            name="null_check_transform",
            version="1.0.0",
            description="Transform C# null checks to C++ nullptr checks",
            priority=90,  # Higher priority (runs before if statement transform)
            phase=TransformationPhase.NORMALIZATION,
            tags=["statement", "null-check", "nullptr"],
        )
        super().__init__(metadata, target_statement_kind="if")

    def can_apply(self, node: Any) -> bool:
        """Check if this is an if statement with null check"""
        if not isinstance(node, IfStatement):
            return False

        # Check if condition contains 'null' keyword
        condition = node.condition.lower()
        return "null" in condition and "==" in condition or "!=" in condition

    def apply(self, node: Any) -> Any:
        """Transform null checks to nullptr checks"""
        if not isinstance(node, IfStatement):
            return node

        # Replace 'null' with 'nullptr'
        transformed_condition = node.condition.replace(" null", " nullptr")
        transformed_condition = transformed_condition.replace("(null", "(nullptr")

        transformed = IfStatement(
            condition=transformed_condition,
            then_block=node.then_block,
            else_block=node.else_block,
            metadata={
                **node.metadata,
                "transformation_applied": "null_to_nullptr",
            },
        )

        return transformed


def register_default_statement_transformers() -> None:
    """Register all default statement transformers with the global registry"""
    from orchestrator.transforms.registry import get_global_registry

    registry = get_global_registry()

    # Register statement transformers
    registry.register(IfStatementTransformer())
    registry.register(ForeachToRangeForTransformer())
    registry.register(NullCheckTransformer())
